﻿using System;
using System.Web;
using System.Collections.Specialized;

namespace MikeKappel.Com.CS.Model
{
    /// <summary>
    /// Specialized NameValueCollection that represents QueryString
    /// </summary>
    public class QueryStringCollection : NameValueCollection
    {
        #region Enumerations
            public enum ToStringType
            {
                Remove,
                Replace
            }
        #endregion
        #region Constructors
            /// <summary>
            /// 
            /// </summary>
            public QueryStringCollection()
                : base(new NameValueCollection(HttpContext.Current.Request.QueryString))
            {
            }

            /// <summary>
            /// 
            /// </summary>
            /// <param name="queryString"></param>
            public QueryStringCollection(String queryString)
                : base(new NameValueCollection(HttpUtility.ParseQueryString(queryString)))
            {

            }
        #endregion
        #region Methodes
            /// <summary>
            /// Remove key/value pairs from QueryString
            /// </summary>
            /// <param name="keys">Keys of QueryString Segments to Remove</param>
            public void Remove(params String[] keys)
            {
                if (this.Count > 0)
                    foreach (String key in keys)
                        if (this[key] != null)
                            base.Remove(key);
            }

            /// <summary>
            /// Replace key/value pair in QueryString
            /// If value is null of empty the segment will be removed
            /// </summary>
            /// <param name="key">Key of QueryString Segment to Replace</param>
            /// <param name="value">New Value</param>
            public void Replace(String key, String value)
            {
                String valueEncoded = HttpUtility.UrlEncode(value);
                if (this[key] != null)
                    if (String.IsNullOrEmpty(value))
                        base.Remove(key);
                    else
                        this[key] = value;
                else if (!String.IsNullOrEmpty(value))
                    this.Add(key, value);
            }
            /// <summary>
            /// Generates a Query String
            /// </summary>
            /// <returns></returns>
            public string CreateQueryString()
            {
                String result = "";
                foreach (String key in Keys)
                    result += String.Concat(((result == "") ? "?" : "&"), key, "=", System.Web.HttpUtility.UrlEncode(this[key]));
  
                return result;
            }
            /// <summary>
            /// Returns QueryString
            /// </summary>
            /// <returns>QueryString</returns>
            public override string ToString()
            {
                return CreateQueryString();
            }

            /// <summary>
            /// Returns QueryString
            /// ToStringType mode is set to "Replace" then key will determine the value that is added or modified
            /// ToStringType mode is set to "Remove" then values and keys related to the keys parameter will be removed
            /// </summary>
            /// <returns>QueryString</returns>
            public string ToString(ToStringType mode, params String[] keys)
            {
                if (mode == ToStringType.Remove)
                    Remove(keys);
                else if (keys.Length > 2 || keys == null || String.IsNullOrEmpty(keys[0]))
                    throw new IndexOutOfRangeException("ToString Replace Mode of QueryStringCollection should have 1 or 2 arguments");
                else if (keys.Length == 2)
                    Replace(keys[0], keys[1]);
                else if (keys.Length == 1)
                    Replace(keys[0], null);

                return CreateQueryString();
            }

            /// <summary>
            /// Returns QueryString
            /// key will determine the value that is added or modified
            /// </summary>
            /// <returns>QueryString</returns>
            public string ToString(String key, String value)
            {
                Replace(key, value);
                return CreateQueryString();
            }

        #endregion
        #region Factory Methods
            public static QueryStringCollection RemoveKeys(params String[] keys)
            {
                QueryStringCollection result = new QueryStringCollection();
                result.Remove(keys);
                return result;
            }
            public static QueryStringCollection ReplaceValue(String key, String value)
            {
                QueryStringCollection result = new QueryStringCollection();
                result.Replace(key, value);
                return result;
            }
        #endregion
    }
}